package tools

import (
	"encoding/json"
	"fmt"

	"anders-cli/internal/ai"
)

// ToolCaller 工具调用器
type ToolCaller struct {
	availableTools map[string]ToolFunction
}

// ToolFunction 工具函数接口
type ToolFunction func(args map[string]interface{}) (string, error)

// NewToolCaller 创建新的工具调用器
func NewToolCaller() *ToolCaller {
	tc := &ToolCaller{
		availableTools: make(map[string]ToolFunction),
	}
	tc.registerTools()
	return tc
}

// registerTools 注册所有可用的工具
func (tc *ToolCaller) registerTools() {
	// 注册内置工具
	tc.availableTools["read_file"] = tc.readFileTool
	tc.availableTools["replace_in_file"] = tc.replaceInFileTool

	// 注册自定义工具
	tc.registerCustomTools()
}

// GetAvailableTools 获取所有可用的工具定义（OpenAI兼容格式）
func (tc *ToolCaller) GetAvailableTools() []ai.Tool {
	var tools []ai.Tool

	// 内置工具
	tools = append(tools, ai.Tool{
		Type: "function",
		Function: struct {
			Name        string                 `json:"name"`
			Description string                 `json:"description"`
			Parameters  map[string]interface{} `json:"parameters"`
		}{
			Name:        "read_file",
			Description: "读取指定文件的内容，支持文本文件和多媒体文件",
			Parameters: map[string]interface{}{
				"type": "object",
				"properties": map[string]interface{}{
					"file_path": map[string]interface{}{
						"type":        "string",
						"description": "要读取的文件路径",
					},
				},
				"required": []string{"file_path"},
			},
		},
	})

	// 替换文件内容工具
	tools = append(tools, ai.Tool{
		Type: "function",
		Function: struct {
			Name        string                 `json:"name"`
			Description string                 `json:"description"`
			Parameters  map[string]interface{} `json:"parameters"`
		}{
			Name:        "replace_in_file",
			Description: "替换文件中的指定字符串",
			Parameters: map[string]interface{}{
				"type": "object",
				"properties": map[string]interface{}{
					"file_path": map[string]interface{}{
						"type":        "string",
						"description": "要修改的文件路径",
					},
					"old_str": map[string]interface{}{
						"type":        "string",
						"description": "要替换的旧字符串",
					},
					"new_str": map[string]interface{}{
						"type":        "string",
						"description": "替换的新字符串",
					},
				},
				"required": []string{"file_path", "old_str", "new_str"},
			},
		},
	})

	// 自定义工具
	customTools := tc.getCustomTools()
	tools = append(tools, customTools...)

	return tools
}

// ExecuteTool 执行指定的工具
func (tc *ToolCaller) ExecuteTool(toolCall interface{}) (string, error) {
	// 处理不同格式的工具调用
	var toolName string
	var args map[string]interface{}

	// 处理 LMStudio/OpenAI 格式的工具调用
	if toolCallMap, ok := toolCall.(map[string]interface{}); ok {
		if function, exists := toolCallMap["function"]; exists {
			if funcMap, ok := function.(map[string]interface{}); ok {
				if name, exists := funcMap["name"]; exists {
					if nameStr, ok := name.(string); ok {
						toolName = nameStr
					}
				}
				if arguments, exists := funcMap["arguments"]; exists {
					if argsStr, ok := arguments.(string); ok {
						json.Unmarshal([]byte(argsStr), &args)
					} else if argsMap, ok := arguments.(map[string]interface{}); ok {
						args = argsMap
					}
				}
			}
		}
	}

	if toolName == "" {
		return "", fmt.Errorf("无法解析工具调用")
	}

	// 执行对应的工具函数
	if toolFunc, exists := tc.availableTools[toolName]; exists {
		result, err := toolFunc(args)
		if err != nil {
			return "", fmt.Errorf("工具执行失败: %v", err)
		}
		return result, nil
	}

	return "", fmt.Errorf("未知工具: %s", toolName)
}

// readFileTool 读取文件工具
func (tc *ToolCaller) readFileTool(args map[string]interface{}) (string, error) {
	filePath, ok := args["file_path"].(string)
	if !ok {
		return "", fmt.Errorf("缺少必需参数: file_path")
	}

	return ReadFile(filePath)
}

// replaceInFileTool 替换文件内容工具
func (tc *ToolCaller) replaceInFileTool(args map[string]interface{}) (string, error) {
	filePath, ok := args["file_path"].(string)
	if !ok {
		return "", fmt.Errorf("缺少必需参数: file_path")
	}

	oldStr, ok := args["old_str"].(string)
	if !ok {
		return "", fmt.Errorf("缺少必需参数: old_str")
	}

	newStr, ok := args["new_str"].(string)
	if !ok {
		return "", fmt.Errorf("缺少必需参数: new_str")
	}

	err := ReplaceInFile(filePath, oldStr, newStr)
	if err != nil {
		return "", err
	}

	return "文件内容替换成功", nil
}
